<?php

/*
 *
 *
 * This software has been made FREELY available by author for interest of the developers. 
 *      I hope this will help you in coding faster and robust php application
 *            You can modify and use it as you it suits you.
 *              Your comments, suggestions and corrections 
 *                          will be highly 
 *                           APPRECIATED. 
 *                                      Thanks, 
 *                                      Author
 * @author :   Roshan Budhathoki (contact@roshanbudhathoki.com);
 * @URL    :   <http://www.roshanbudhathoki.com>
 *
 */

class Rewrite {
	
	private static $instance;
	private $rules;
	private $request_uri;
	private $uri;
	private $location;
	private $section;
	private $page;
	private $slug;
	
	public function __construct() {
		$this->rules = $this->getRules ();
		$this->request_uri = '';
		$this->uri = '';
		$this->location = '';
		$this->section = '';
		$this->page = '';
		$this->slug = '';
	}
	
	public static function newInstance() {
		if (! self::$instance instanceof self) {
			self::$instance = new self ();
		}
		return self::$instance;
	}
	
	public function getRules() {
		$rules = array ();
		/* Add rule for per item */
		$rules ['^/item/([0-9a-zA-Z]+)/([0-9a-zA-Z]+)/?'] = 'index.php?page=item&action=$1&secret=$2';
		$rules ['^/item/([0-9a-zA-Z]+)/?'] = 'index.php?page=item&action=$1';
		$rules ['^/unit/?$'] = 'index.php?page=unit';
		$rules ['^/user/?$'] = 'index.php?page=user&action=dashboard';
		$rules ['^/user/dashboard/?'] = 'index.php?page=user&action=dashboard';
		$rules ['^/user/register/?'] = 'index.php?page=user&action=register';
		$rules ['^/user/sign-in/?'] = 'index.php?page=user&action=sign-in';
		$rules ['^/user/sign-out/?'] = 'index.php?page=user&action=sign-out';
		$rules ['^/user/activate/([0-9a-zA-Z]+)/?'] = 'index.php?page=user&action=activate&secret=$1';
		$rules ['^/search/?$'] = 'index.php?page=search';
		$rules ['^/ajax/([0-9a-zA-Z]+)/?'] = 'index.php?page=ajax&action=$1';
		$rules ['^/page/?$'] = 'index.php?page=page';
		$rules ['^/tag/([0-9a-zA-Z]+)/?'] = 'index.php?page=tag&tag=$1';
		$rules ['^/$'] = 'index.php?page=home';
		return $rules;
	}
	
	public function setRules() {
	
	}
	
	public function listRules() {
		return $this->rules;
	}
	
	public function addRules($rules) {
		if (is_array ( $rules )) {
			foreach ( $rules as $rule ) {
				if (is_array ( $rule ) && count ( $rule ) > 1) {
					$this->addRule ( $rule [0], $rule [1] );
				}
			}
		}
	}
	
	public function addRule($regexp, $uri) {
		$regexp = trim ( $regexp );
		$uri = trim ( $uri );
		if ($regexp != '' && $uri != '') {
			if (! in_array ( $regexp, $this->rules )) {
				$this->rules [$regexp] = $uri;
			}
		}
	}
	
	public function init() {
		// $_SERVER is not supported by Params Class... we should fix that
		if (isset ( $_SERVER ['REQUEST_URI'] )) {
			$match_found = FALSE; // default to false means its cateogry or product or page or location with index action
			//define('REL_WEB_URL', '');
			//$request_uri = urldecode(preg_replace('@^' . REL_WEB_URL . '@', "", $_SERVER['REQUEST_URI']));
			
			$request_uri = $_SERVER ['REQUEST_URI'];
			
			// EXTRACT GET PARAMS BEFORE PARSING URI REWRITE
			$this->extractParams ( $request_uri );
			$tmp_ar = explode ( "?", $request_uri );
			$request_uri = $tmp_ar [0];
			
			unset ( $tmp_ar ); // unset array
			
			// CHECK FOR / AT THE END OF URI AND ADD IF IT DOES NOT HAVE TO AVOID BUG
			$len = strlen ( $request_uri ) - 1;
			if ($len > strrpos ( $request_uri, '/' )) {
				$request_uri = $request_uri . '/';
			}
			
			// NOW GET URI JUST WITHOUT LAST / 
			if (strrpos ( $request_uri, '/' )) {
				$request_uri = substr ( $request_uri, 0, strrpos ( $request_uri, '/' ) );
			}
			
			$this->request_uri = $request_uri;
			
			/*
			 ****************************************************
			 * NOW MATCH THE REWRITE RULES WITH THE REQUEST URI
			 * **************************************************
			 */
			
			foreach ( $this->rules as $match => $uri ) {
				// UNCOMMENT TO DEBUG
				//echo 'Request URI: ' . $request_uri . " # Match : " . $match . " # URI to go : " . $uri . " <br />";
				if (preg_match ( '#' . $match . '#', $request_uri, $m )) {
					$request_uri = preg_replace ( '#' . $match . '#', $uri, $request_uri );
					//echo $request_uri;
					$match_found = TRUE;
					break;
				}
			}
			
			if (! $match_found) {
				
				// ADD slash at the end of uri if it does not have one
				$len = strlen ( $request_uri ) - 1;
				if ($len > strrpos ( $request_uri, '/' )) {
					$request_uri = $request_uri . '/';
				}
				
				$request_uri = substr ( $request_uri, strpos ( $request_uri, '/' ) + 1 );
				
				// echo $request_uri;
				if (strrpos ( $request_uri, '/' )) {
					$request_uri = substr ( $request_uri, 0, strrpos ( $request_uri, '/' ) );
				}
				
				//echo $request_uri;
				

				// echo $request_uri;
				$parts = explode ( '/', $request_uri );
				
				if (count ( $parts ) < 1) {
					echo 'URL PARSING ABORTED.';
				}
				
				$first_item = $parts [0];
				
				/*
				 * *****************************************
				 * Check if location exists
				 * *****************************************
				 */
				
				$location = Model_Mapper_Locations::newInstance ()->getBySlug ( $first_item );
				if ($location) {
					// location exits now set to params class
					Params::setParam ( 'location', $location );
					Params::setParam ( 'location_exists', 1 );
				}
				
				/*// GET ALL THE CATEGORIES AND LOCATIONS INSIDE THE URL;
				foreach ( $parts as $key => $value ) {
					
					$result = Model_Mapper_Categories::newInstance ()->getBySlug ( $value );
					$location = Model_Mapper_Locations::newInstance ()->getBySlug ( $value );
					
					//print_r ( $result );
					if ($result && $location) {
						Params::setParam ( 'category', $result );
						$category = true;
						Params::setParam ( 'location', $location );
						$location = true;
						break;
					} else if ($result) {
						// its category
						Params::setParam ( 'category', $result );
						$category = true;
						break;
					} elseif ($location) {
						// its Location
						Params::setParam ( 'location', $location );
						$location = true;
						break;
					}
				}*/
				
				// NOW CHECK LAST PART TO DETERMINE LOCATION / CATEGORY  OR ITEM OR PAGE
				// PARSING ORDER ==> ITEM / CATEGORY / LOCATION / PAGE
				

				$parts = array_reverse ( $parts );
				
				$slug = $parts [0];
				
				$this->slug = $slug; // set current slug;
				Params::setParam ( 'slug', $slug ); // set slug Param
				

				if (Model_Mapper_Items::newInstance ()->getBySlug ( $slug )) {
					$this->page = 'item';
					Params::setParam ( 'page', 'item' );
					$this->section = 'index';
					Params::setParam ( 'action', 'index' );
				
				} else if (Model_Mapper_Categories::newInstance ()->getBySlug ( $slug )) {
					$this->page = 'category';
					Params::setParam ( 'page', 'category' );
					$this->section = 'index';
					Params::setParam ( 'action', 'index' );
					Params::setParam ( 'category', Model_Mapper_Categories::newInstance ()->getBySlug ( $slug ) );
				
				} else if (Model_Mapper_Locations::newInstance ()->getBySlug ( $slug )) {
					// its location
					$this->page = 'location';
					Params::setParam ( 'page', 'location' );
					$this->section = 'index';
					Params::setParam ( 'action', 'index' );
				
				} else if (false) { // add page check later
					$this->page = 'page';
					Params::setParam ( 'page', 'page' );
					$this->section = 'index';
					Params::setParam ( 'action', 'index' );
				} elseif ($slug == ADMIN) {
					$this->page = ADMIN;
					Params::setParam ( 'CP', true );
				} else if ($slug == 'ajax') {
					$this->page = 'ajax';
					Params::setParam ( 'page', 'ajax' );
				} else if ($slug == 'unit') {
					$this->page = 'unit';
					Params::setParam ( 'page', 'unit' );
				} else {
					// its 404
					$this->page = '404';
					Params::setParam ( 'page', '404' );
					$this->section = 'index';
					Params::setParam ( 'action', 'index' );
				
				}
			
			} else {
				
				$this->extractParams ( $request_uri );
				$this->request_uri = $request_uri;
				
				if (Params::getParam ( 'page' ) != '') {
					$this->location = Params::getParam ( 'page' );
				}
				
				if (Params::getParam ( 'action' ) != '') {
					$this->section = Params::getParam ( 'action' );
				}
			
			}
		}
	}
	
	public function extractURL($uri = '') {
		$uri_array = explode ( '?', str_replace ( 'index.php', '', $uri ) );
		if (substr ( $uri_array [0], 0, 1 ) == "/") {
			return substr ( $uri_array [0], 1 );
		} else {
			return $uri_array [0];
		}
	}
	
	public function extractParams($uri = '') {
		$uri_array = explode ( '?', $uri );
		$url = substr ( $uri_array [0], 1 );
		$length_i = count ( $uri_array );
		for($var_i = 1; $var_i < $length_i; $var_i ++) {
			if (preg_match_all ( '|&([^=]+)=([^&]*)|', '&' . $uri_array [$var_i] . '&', $matches )) {
				$length = count ( $matches [1] );
				for($var_k = 0; $var_k < $length; $var_k ++) {
					Params::setParam ( $matches [1] [$var_k], str_replace ( '/', '', $matches [2] [$var_k] ) );
				}
			}
		}
	}
	
	public function removeRule($regexp) {
		unset ( $this->rules [$regexp] );
	}
	
	public function clearRules() {
		unset ( $this->rules );
		$this->rules = array ();
	}
	
	public function get_request_uri() {
		return $this->request_uri;
	}
	
	public function set_location($location) {
		$this->location = $location;
	}
	
	public function get_location() {
		return $this->location;
	}
	
	public function get_section() {
		return $this->section;
	}

}